package com.hyt.it.ogt.kq.service.gov.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Maps;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.it.ogt.kq.common.gov.constant.ArrangeParamCodeEnum;
import com.hyt.it.ogt.kq.common.gov.constant.CodeEnum;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.gov.constant.StringCodeEnum;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.service.gov.mapper.OfficeTimeRoomParamMapper;
import com.hyt.it.ogt.kq.service.gov.mapper.TimeRoomParamMapper;
import com.hyt.it.ogt.kq.service.gov.model.entity.*;
import com.hyt.it.ogt.kq.service.gov.model.param.RoomTypeUpdateParam;
import com.hyt.it.ogt.kq.service.gov.model.vo.examiner.TimeRoomParamVO;
import com.hyt.it.ogt.kq.service.gov.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 考生编排信息表 服务实现类
 * </p>
 *
 * @author huangyh
 * @since 2021-04-08
 */
@Service
@Slf4j
public class TimeRoomParamServiceImpl extends BaseServiceImpl<TimeRoomParamMapper, TimeRoomParam> implements ITimeRoomParamService {

    @Resource
    private IOfficeTimeRoomParamService officeTimeRoomParamService;

    @Resource
    private ITaskService taskService;

    @Resource
    private OfficeTimeRoomParamMapper officeTimeRoomParamMapper;

    @Resource
    private TimeRoomParamMapper timeRoomParamMapper;

    @Resource
    private ITimeRoomService iTimeRoomService;

    @Resource
    private ITaskPlaceService iTaskPlaceService;

    @Resource
    private ITaskRoomService iTaskRoomService;

    @Resource
    private ITimeRoomCandidateService iTimeRoomCandidateService;

    @Resource
    private ITaskService iTaskService;
    @Resource
    private ICandidateService iCandidateService;

    /**
     * 初始化编排参数
     * @param taskId
     * @param officeId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void initTaskTimeRoomParam(String taskId, String officeId) {

        //清除任务的参数
        LambdaUpdateWrapper<TimeRoomParam> lambdaUpdateWrapper = new LambdaUpdateWrapper<TimeRoomParam>();
        lambdaUpdateWrapper.eq(TimeRoomParam::getTaskId,taskId)
                .eq(TimeRoomParam::getDelFlag,false)
                .set(TimeRoomParam::getDelFlag,true);
        this.update(lambdaUpdateWrapper);
        //插入任务模板数据
        officeTimeRoomParamMapper.initOfficeAndTaskTimeRoomParam(officeId, taskId,null);
    }

    /**
     * 从机构参数拉取数据
     * @param taskId
     * @param officeId
     */
    @Override
    public void initTaskTimeRoomParamFromOffice(String taskId, String officeId) {
        Integer count = this.lambdaQuery()
                .eq(TimeRoomParam::getTaskId,taskId)
                .eq(TimeRoomParam::getDelFlag,false)
                .count();
        if (count <= 0) {
            //校验和初始机构编排参数
            //officeTimeRoomParamService.initOfficeTaskTimeRoomParam(officeId);
            //初始化任务编排参数
            baseMapper.initTaskTimeRoomParamFromOffice(taskId,officeId);
        }
    }

    /**
     * 批量更新编排参数
     * @param timeRoomParamVOList
     */
    @Override
    public void updateTaskTimeRoomParam(List<TimeRoomParamVO> timeRoomParamVOList) {

        List<TimeRoomParam> timeRoomParamList = new ArrayList<>();
        timeRoomParamVOList.stream().forEach(timeRoomParamVO -> {
            TimeRoomParam timeRoomParam = new TimeRoomParam();
            timeRoomParam.setValue(timeRoomParamVO.getValue())
                    .setId(timeRoomParamVO.getId());
            timeRoomParamList.add(timeRoomParam);
        });

        if (timeRoomParamList != null && !timeRoomParamList.isEmpty()) {
            this.updateBatchById(timeRoomParamList);
        }

    }

    @Override
    public void updateTaskTimeRoomParam(String taskId,String code,String value) {

        if (iTimeRoomCandidateService.countArrangedCandidate(taskId) > 0) {
            //1.如果存在编排数据则，不允许解除
            throw new KqException(ResponseCode.ERROR_OVERVIEW_HAS_ARRANGED.getCode(), ResponseCode.ERROR_OVERVIEW_HAS_ARRANGED.getMsg());
        }

        //3.1 必须在updateTaskTimeRoomParam前执行，如果更换考场模式，则清除考点考场数据，如果是虚拟考场，则会初始化一个虚拟的考点出来。
        removePlaceRoomTime(taskId,value);

        this.lambdaUpdate()
                .eq(TimeRoomParam::getTaskId,taskId)
                .eq(TimeRoomParam::getDelFlag,false)
                .eq(TimeRoomParam::getCode,code)
                .set(TimeRoomParam::getValue,value)
                .update();

        TimeRoomParam param = this.lambdaQuery().eq(TimeRoomParam::getTaskId,taskId)
                .eq(TimeRoomParam::getDelFlag,false)
                .eq(TimeRoomParam::getCode,StringCodeEnum.ARRANGE_PARAM_ARRANGE_RULE.getCode()).one();
        //重置规则项
        if (ObjectUtil.isNotEmpty(param) && "3".equals(param.getValue()) && "1".equals(value)){
            this.lambdaUpdate()
                    .eq(TimeRoomParam::getTaskId,taskId)
                    .eq(TimeRoomParam::getDelFlag,false)
                    .eq(TimeRoomParam::getCode,StringCodeEnum.ARRANGE_PARAM_ARRANGE_RULE.getCode())
                    .set(TimeRoomParam::getValue,0)
                    .update();
        } else if(ObjectUtil.isNotEmpty(param) && "2".equals(param.getValue()) && "0".equals(value)){
            this.lambdaUpdate()
                    .eq(TimeRoomParam::getTaskId,taskId)
                    .eq(TimeRoomParam::getDelFlag,false)
                    .eq(TimeRoomParam::getCode,StringCodeEnum.ARRANGE_PARAM_ARRANGE_RULE.getCode())
                    .set(TimeRoomParam::getValue,0)
                    .update();
        }
    }


    /**
     * 编排时,切换考场模式时，自动删除对应的数据。
     * @param taskId
     * @param roomType
     */
    private void removePlaceRoomTime(String taskId,String roomType) {
        //3.1 如果更换考场模式，则清除考点考场数据，如果是虚拟考场，则会初始化一个虚拟的考点出来。
        //虚拟考场参数是否一致
//        Boolean flag = this.AreConsistentRoomType(taskId,roomType);
        if (roomType.equals(String.valueOf(ArrangeParamCodeEnum.ARRANGE_ROOM_TYPE_VIRTUAL.getCode()))) {
            //参数前后不一致需要清除考点考场数据
            Boolean flag_time_data = iTimeRoomService.AreTimeRoomData(taskId);
            if (roomType.equals(String.valueOf(ArrangeParamCodeEnum.ARRANGE_ROOM_TYPE_VIRTUAL.getCode())) && flag_time_data) {
                //如果实体考场转虚拟考场，则需要验证实体考场是否绑定批次，如果是，则不允许切换。
                throw new KqException(ResponseCode.TIME_ROOM_BIND_PHYSICAL_EXCEPTION.getCode(),
                        ResponseCode.TIME_ROOM_BIND_PHYSICAL_EXCEPTION.getMsg());
            }

            //删除数据，考点，考场，场次
            iTaskPlaceService.lambdaUpdate()
                    .eq(TaskPlace::getTaskId,taskId)
                    .eq(TaskPlace::getDelFlag,false)
                    .set(TaskPlace::getDelFlag,true)
                    .update();

            //删除数据，考点，考场，场次
            iTaskRoomService.lambdaUpdate()
                    .eq(TaskRoom::getTaskId,taskId)
                    .eq(TaskRoom::getDelFlag,false)
                    .set(TaskRoom::getDelFlag,true)
                    .update();

            //删除数据，考点，考场，场次
            iTimeRoomService.lambdaUpdate()
                    .eq(TimeRoom::getTaskId,taskId)
                    .eq(TimeRoom::getDelFlag,false)
                    .set(TimeRoom::getDelFlag,true)
                    .update();
        }

    }

    @Override
    public void updateTaskTimeRoomParamRoomType(RoomTypeUpdateParam roomTypeUpdateParam) {
        updateTaskTimeRoomParam(roomTypeUpdateParam.getTaskId(),StringCodeEnum.ARRANGE_PARAM_ARRANGE_TYPE.getCode(),roomTypeUpdateParam.getRoomType());
    }

    /**
     * 获取编排参数
     * @param taskId
     * @return
     */
    @Override
    public List<TimeRoomParamVO> getTaskTimeRoomParam(String taskId) {
        return baseMapper.selectTimeRoomParamByTaskId(taskId);
    }

    /**
     * 获取code对应的值
     * @param taskId
     * @return
     */
    @Override
    public String getTaskTimeRoomParamValueByCode(String taskId, String code) {

        TimeRoomParam timeRoomParam = this.lambdaQuery()
                .eq(TimeRoomParam::getTaskId,taskId)
                .eq(TimeRoomParam::getCode,code)
                .eq(TimeRoomParam::getDelFlag,false)
                .last("limit 1")
                .one();

        String paramValue = null;
        if (timeRoomParam != null) {
            paramValue = timeRoomParam.getValue();
        }

        return paramValue;
    }

    @Override
    public void copyTimeRoomParam(String oldTaskId, String newTaskId, String userName) {
        timeRoomParamMapper.copyTimeRoomParam(oldTaskId, newTaskId, userName);
    }

    @Override
    public Map<String,String> getTimeRoomParamMap(List<TimeRoomParamVO> timeRoomParamList, String taskId) {
        Map<String,String> paramMap = Maps.newHashMap();

        if (timeRoomParamList == null || timeRoomParamList.isEmpty()) {
            timeRoomParamList = getTaskTimeRoomParam(taskId);
        }

        timeRoomParamList.stream().forEach(timeRoomParam -> {
            paramMap.put(timeRoomParam.getCode(),timeRoomParam.getValue());
        });

        //区域编排，默认编排自增序号，0：区域，1：市，2：省，3：考区
        paramMap.put("areaArrangeAuto", ArrangeParamCodeEnum.AREA_ARRANGE_LEVEL_DISTRICT.getCode().toString());
        return paramMap;
    }

    @Override
    public Boolean AreConsistent(String taskId,String newParamCode,String newParamValue) {
        String oldParamValue = getTaskTimeRoomParamValueByCode(taskId,newParamCode);
        if (oldParamValue.equals(newParamValue)) {
            return true;
        }
        return false;
    }

    @Override
    public Boolean AreConsistentRoomType(String taskId,String newParamValue) {
        return AreConsistent(taskId,StringCodeEnum.ARRANGE_PARAM_ARRANGE_TYPE.getCode(),newParamValue);
    }

    @Override
    public Boolean AreVirtualRoom(String taskId) {
        String roomType = this.getTaskTimeRoomParamValueByCode(taskId,StringCodeEnum.ARRANGE_PARAM_ARRANGE_TYPE.getCode());
        log.info("当前的考场类型：{}",roomType);
        if (String.valueOf(ArrangeParamCodeEnum.ARRANGE_ROOM_TYPE_VIRTUAL.getCode()).equals(roomType)) {
            return true;
        }
        return false;
    }

    @Override
    public List<TimeRoomParam> listValueByTaskIdsAndCode(List<String> taskIdList, String code) {
        return this.lambdaQuery().select(TimeRoomParam::getTaskId, TimeRoomParam::getValue)
                .in(TimeRoomParam::getTaskId, taskIdList)
                .eq(TimeRoomParam::getCode, code)
                .eq(TimeRoomParam::getDelFlag, Boolean.FALSE)
                .list();
    }

    @Override
    public TimeRoomParam oneValueByTaskIdAndCode(String taskId, String code) {
        return this.lambdaQuery().select(TimeRoomParam::getTaskId, TimeRoomParam::getValue)
                .eq(TimeRoomParam::getTaskId, taskId)
                .eq(TimeRoomParam::getCode, code)
                .eq(TimeRoomParam::getDelFlag, Boolean.FALSE)
                .last("LIMIT 1")
                .one();
    }

}
